package com.mycontract.suitepro.components.processBar

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.DisplayMetrics
import android.util.TypedValue
import android.view.View
import androidx.core.content.ContextCompat
import com.mycontract.suitepro.R
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*

class GradientProcessBar : View {

    //进度条颜色（渐变色的2个点）
    private val mColors = intArrayOf(Color.RED, Color.MAGENTA)

    //进度条默认颜色
    private var backgroundColor = Color.RED

    //进度条画笔
    private var mPaint: Paint

    //进度条背景笔
    private var mPaintBg: Paint

    //背景进度条
    private var mPathBg: Path

    //进度条
    private var mPath: Path

    //进度条作用区间
    private var mRectF: RectF

    //背景进度条作用区间
    private var mRectFBg: RectF

    //循环flow
    private var mLooperFlow: Job? = null

    //进度值
    private var mProgressValue = 0

    //进度条总长度
    private val mMaxProcessValue = 1000

    constructor(context: Context?) : this(context, null)
    constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : this(
        context,
        attrs,
        defStyleAttr,
        0
    )

    @SuppressLint("Recycle")
    constructor(
        context: Context?,
        attrs: AttributeSet?,
        defStyleAttr: Int,
        defStyleRes: Int,
    ) : super(
        context,
        attrs,
        defStyleAttr,
        defStyleRes
    ) {
        attrs?.let {
            context?.let {
                it.obtainStyledAttributes(attrs, R.styleable.GradientProcessBar).apply {
                    mColors[0] = getColor(
                        R.styleable.GradientProcessBar_aiProcessBarStartColor,
                        ContextCompat.getColor(
                            context,
                            R.color.contract_data_uploading_process_start_color
                        )
                    )

                    mColors[1] = getColor(
                        R.styleable.GradientProcessBar_aiProcessBarEndColor,
                        ContextCompat.getColor(
                            context,
                            R.color.contract_data_uploading_process_start_color
                        )
                    )

                    backgroundColor = getColor(
                        R.styleable.GradientProcessBar_aiProcessBarBackgroundColor,
                        ContextCompat.getColor(
                            context,
                            R.color.contract_data_uploading_process_background_color
                        )
                    )
                }
            }
        }

        //设置背景
        mPathBg = Path()
        mPath = Path()

        //设置作用区间
        mRectF = RectF()
        mRectFBg = RectF()

        // 设置画笔
        mPaint = Paint()
        mPaint.isAntiAlias = true
        mPaint.style = Paint.Style.FILL
        mPaint.strokeCap = Paint.Cap.ROUND
        mPaint.color = backgroundColor

        // 设置背景进度条画笔
        mPaintBg = Paint()
        mPaintBg.isAntiAlias = true
        mPaintBg.style = Paint.Style.FILL
        mPaintBg.strokeCap = Paint.Cap.ROUND
        mPaintBg.color = backgroundColor

        // 设置进度
        mProgressValue = 0
    }

    /** 设置进度 */
    fun setProgressValue(progressValue: Int) {
        mProgressValue = progressValue.coerceAtMost(mMaxProcessValue)
        println("cur process: $mProgressValue")
        postInvalidate()

        //val progressValueInt = progressValue.coerceAtMost(mMaxProcessValue)
//        val progressAnimator = ValueAnimator.ofInt(progressValueInt)
//        progressAnimator.duration = 100
//        progressAnimator.addUpdateListener {
//            val value: Int = it.animatedValue as Int
//            mProgressValue = value
//            invalidate()
//        }
//        progressAnimator.start()
    }

    /** 设置渐变色 */
    fun setColors(colors: IntArray) {
        if (colors.size >= 2) {
            mColors[0] = colors[0]
            mColors[1] = colors[1]
            println("cur colors: $colors")
        }
    }

    /** 清空流程 */
    fun release() {
        mLooperFlow?.cancel()
    }

    /** 设置定时跑进度 */
    fun startTimerLooper(scope: CoroutineScope, onTick: (Int) -> Unit) {
        //取消原来进度
        mLooperFlow?.cancel()

        //初始化进度
        mLooperFlow = initLooperFlow(scope, mMaxProcessValue,
            {
                val toPercent = it / 10
                println("flow $it  $toPercent")
                //转成百分比再回调给上层页面
                onTick(toPercent)
                setProgressValue(it)
                if (it == mMaxProcessValue) {
                    mLooperFlow?.cancel()
                }
            }, {})
    }

    /** 设置进度完成 */
    fun setFinishDirectly(onTick: (Int) -> Unit, onFinish: () -> Unit) {
        //取消原来进度
        mLooperFlow?.cancel()

        //计算剩余进度
        //1000-689 = 321
        val didRunProcessValue = (mProgressValue + 1)
        val remainProcessValue = (mMaxProcessValue - didRunProcessValue)
        println("setFinishDirectly $didRunProcessValue  $remainProcessValue")

        //如果已经完成，直接返回
        if (remainProcessValue <= 0) {
            onFinish.invoke()
            return
        }

        //设置百分比动画
        val percentAnimator = ValueAnimator.ofInt(didRunProcessValue, mMaxProcessValue)
        percentAnimator.duration = remainProcessValue.toLong()
        percentAnimator.addUpdateListener {
            val value: Int = it.animatedValue as Int
            val toPercent = value / 10
            println("percentAnimator: $value $toPercent")
            onTick(toPercent)
        }
        percentAnimator.start()

        //设置进度比动画
        val progressAnimator = ValueAnimator.ofInt(didRunProcessValue, mMaxProcessValue)
        progressAnimator.duration = remainProcessValue.toLong()
        progressAnimator.addUpdateListener {
            val value: Int = it.animatedValue as Int
            println("progressAnimator: $value")
            mProgressValue = value
            invalidate()
            if(value==mMaxProcessValue){
                onFinish.invoke()
            }
        }
        progressAnimator.start()
    }

    /** 设置循环流程 */
    private fun initLooperFlow(
        scope: CoroutineScope,
        maxCount: Int = 1000,
        onTick: (Int) -> Unit,
        onFinish: () -> Unit,
    ): Job {
        return flow {
            for (tickSec in 0..maxCount) {
                emit(tickSec)
                delay(100)
            }
        }.flowOn(Dispatchers.Main)
            .onEach { onTick.invoke(it) }
            .onCompletion { onFinish.invoke() }
            .launchIn(scope)
    }

    @SuppressLint("DrawAllocation")
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        //radius
        val mRadius = dp2px(context, height * 1F / 2)

        //设置背景进度条
        mRectFBg.left = 0F
        mRectFBg.top = 0F
        mRectFBg.bottom = height.toFloat()
        mRectFBg.right = width.toFloat()

        //画背景进度条
        mPathBg.addRoundRect(
            mRectFBg,
            mRadius.toFloat(),
            mRadius.toFloat(),
            Path.Direction.CW
        )
        canvas.drawPath(mPathBg, mPaintBg)

        //设置渐变色区域
        val shader = LinearGradient(
            0F,
            0F,
            width * 1F,
            height * 1F,
            mColors,
            null,
            Shader.TileMode.CLAMP
        )
        mPaint.shader = shader

        //画渐变进度条
        var progressValue = mProgressValue * 1F / 1000 * width
        progressValue = progressValue.coerceAtMost(width.toFloat())
        //println("width: $width progressValue $progressValue")

        mRectF.left = 0F
        mRectF.top = 0F
        mRectF.right = progressValue
        mRectF.bottom = height.toFloat()
        mPath.addRoundRect(
            mRectF,
            mRadius.toFloat(),
            mRadius.toFloat(),
            Path.Direction.CW
        )
        canvas.drawPath(mPath, mPaint)

        //重置
        mPath.reset()
        mPathBg.reset()
    }

    private fun getDisplayMetrics(context: Context): DisplayMetrics {
        return context.resources.displayMetrics
    }

    fun dp2px(context: Context, dipValue: Float): Int {
        return TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            dipValue,
            getDisplayMetrics(context)
        ).toInt()
    }
}